package vsvm.math.statistics.histogram;

import java.util.Arrays;
import java.util.Iterator;

import vsvm.data.model.*;
import vsvm.math.CoreMath;
import vsvm.math.statistics.Characteristics;

public class Histogram {	
	
	private HistogramData histData = null;
	private int intervalCnt = 0;
	private double maxFreq = 0.0;
	
	private double[] attrData = null;
	private int attributeType = AbstractAttribute.NUMERIC_TYPE;
	private int n;
	
	
	public Histogram(AbstractDataModel dataModel, AbstractAttribute attribute)
	{
		this.n = dataModel.getVectorCount();
		this.attrData = new double[n];
		System.arraycopy(dataModel.getAttributeData(attribute), 0, attrData, 0, n);		
		this.attributeType = attribute.getAttributeType();
		this.histData = new HistogramData(attribute.getAttributeType());
		prepareData();
	}
	
	public Histogram(AbstractDataModel dataModel, AbstractAttribute attribute, int IntervalCnt)
	{
		this.n = dataModel.getVectorCount();
		this.attrData = new double[n];
		System.arraycopy(dataModel.getAttributeData(attribute), 0, attrData, 0, n);		
		this.attributeType = attribute.getAttributeType();
		this.intervalCnt = intervalCnt;
		this.histData  = new HistogramData(attribute.getAttributeType());
		prepareData();
		
		
	}
	
	public Histogram(double[] data, int type) {
		
		this.n = data.length;
		this.attrData = new double[n];
		System.arraycopy(data, 0, this.attrData, 0, n);		
		this.attributeType = type;
		this.histData = new HistogramData(type);
		prepareData();
		
	}
	
	private void prepareData()
	{
		Arrays.sort(attrData);		
		
		switch(this.attributeType)
		{
			case AbstractAttribute.CATEGORIAL_TYPE:
			{
				intervalCnt = 0;
				double current = attrData[0]; int cnt = 0;
				
				for (int i = 0; i < n; i++){
					
					if (Math.abs(current - attrData[i]) < CoreMath.EPS) cnt++;
					else{
						double freq = (double)cnt/n;
						if (freq > maxFreq) maxFreq = freq;						
						
						histData.addItem(new HistogramItem("" + current , current, current, freq)); //TODO kategorijos vardas
						current = attrData[i];
						cnt = 0;
						intervalCnt++;
					}			
				}
				if (cnt != 0){
					double freq = (double)cnt/n;
					if (freq > maxFreq) maxFreq = freq;
					histData.addItem(new HistogramItem("" + current , freq)); //todo kategorijos vardas
					intervalCnt++;
				}
			}
			break;
			
			case AbstractAttribute.NUMERIC_TYPE:
			{
				if (this.intervalCnt == 0)
					this.intervalCnt = (int) Math.round(1 + 3.222*Math.log10(n));			
				
				double range = attrData[n - 1] - attrData[0];
				double step  = range/intervalCnt;
				int cnt = 1; //Pirma elementa itraukiam i pirma intervala			
				double start = attrData[0]; double end = attrData[0] + step;
				int i = 1;
				while (i < n && start == attrData[i]) { ++cnt; ++i; }
				for (; i < n; i++){					
					if (start < attrData[i] && (attrData[i] < end || Math.abs(attrData[i] - end) < CoreMath.EPS)) cnt++;				
					else{
						double freq = (double)cnt/n;
						if (freq > maxFreq) maxFreq = freq;
						histData.addItem(new HistogramItem(start, end, freq));
						start = end;
						end = start + step;
						cnt = 0;					
					}
				}
				if (cnt != 0){
					double freq = (double)cnt/n;
					if (freq > maxFreq) maxFreq = freq;
					histData.addItem(new HistogramItem(start, end, freq));
				}
					
			}		
		}
		
	}
	
	public int getIntervalCnt()
	{
		return this.intervalCnt;
	}
	
	public HistogramData getHistogramData()
	{
		return this.histData;
	}
	
	public double getMaxFrequency()
	{
		return this.maxFreq;
	}
}
